package org.lwjgl.demo;

import org.lwjgl.*;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import org.lwjgl.system.MemoryStack;

import java.nio.*;

import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryStack.*;
import static org.lwjgl.system.MemoryUtil.*;/**
 * description: TODO
 *
 * @author zhoudy
 * @date 2025/10/29 20:48
 */
public class Demon {


        // 窗口句柄
        private long window;

        public static void main(String[] args) {
            new Demon().run();
        }

        public void run() {
            System.out.println("Hello LWJGL " + Version.getVersion() + "!");

            init();
            loop();

            // 释放资源并清理 GLFW
            glfwFreeCallbacks(window);
            glfwDestroyWindow(window);
            glfwTerminate();
            glfwSetErrorCallback(null).free();
        }

        private void init() {
            System.out.println("1. 设置错误回调...");
            // 设置一个错误回调，用于打印错误信息
            GLFWErrorCallback.createPrint(System.err).set();

            // 初始化 GLFW
            System.out.println("2. 初始化GLFW...");
            if (!glfwInit()) {
                throw new IllegalStateException("Unable to initialize GLFW");
            }

            // 配置 GLFW 窗口
            glfwDefaultWindowHints();
            glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // 初始时窗口隐藏
            glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // 窗口可调整大小

            // 尝试这些兼容性配置
            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
            glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
            glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);

            // 对于某些系统，尝试使用兼容模式
            glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
            glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);

            // 创建窗口
            System.out.println("3. 即将创建窗口...");
            // 在debug模式下，可以尝试添加超时机制
            new Thread(() -> {
                try {
                    Thread.sleep(5000); // 5秒超时
                    System.out.println("⚠️  窗口创建可能卡住了，检查图形驱动...");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
            window = glfwCreateWindow(300, 200, "我的第一个 GLFW 窗口", NULL, NULL);

            System.out.println("4. 窗口创建完成，handle: " + window);
            if (window == NULL) {
                throw new RuntimeException("Failed to create the GLFW window");
            }

            System.out.println("✅ 窗口创建成功");
            // 设置键盘输入的回调
            glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> {
                if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE) {
                    // 当用户按下 ESC 键时，设置窗口需要关闭的标志
                    glfwSetWindowShouldClose(window, true);
                }
            });

            // 获取线程栈并推送一个新的帧
            try (MemoryStack stack = stackPush()) {
                IntBuffer pWidth = stack.mallocInt(1); // int*
                IntBuffer pHeight = stack.mallocInt(1); // int*

                // 获取窗口大小
                glfwGetWindowSize(window, pWidth, pHeight);

                // 获取主监视器的视频模式，以便将窗口居中显示
                GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());

                // 计算窗口位置使其居中
                glfwSetWindowPos(
                        window,
                        (vidmode.width() - pWidth.get(0)) / 2,
                        (vidmode.height() - pHeight.get(0)) / 2
                );
            } // 栈帧在 try-with-resources 块结束后自动弹出

            // 使 OpenGL 上下文成为当前上下文
            glfwMakeContextCurrent(window);
            // 启用 v-sync（垂直同步）
            glfwSwapInterval(1);

            // 现在才显示窗口！
            glfwShowWindow(window);
        }

        private void loop() {
            System.out.println("Hello LWJGL： in loop()!");
            // 这一行对于 LWJGL 至关重要，它初始化了 OpenGL 的绑定
            GL.createCapabilities();

            // 设置清屏颜色（这里是深蓝色）
            glClearColor(0.1f, 0.2f, 0.4f, 0.0f);

            // 运行渲染循环，直到用户尝试关闭窗口
            while (!glfwWindowShouldClose(window)) {
                // 1. 清屏（用上面设置的颜色）
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

                // 2. 在这里放置你的渲染代码！
                // 例如，可以画一个三角形、一个矩形等等。
                // 现在我们先什么都不画，只显示清屏的颜色。

                // 3. 交换颜色缓冲区
                glfwSwapBuffers(window);

                // 4. 轮询事件（如键盘、鼠标事件）
                glfwPollEvents();
            }
        }


}
